Performance improvement

字符串优化 (Strings)

1. 优先使用内置函数

2. 字符替换策略

strtr($str, 'abc', '123'); // ✅ 效率高
strtr($str, ['a' => '1']); // ❌ 效率相对较低

3. 输出与引号

语句与流程控制 (Statements)

1. 避免使用错误抑制符 @

2. 循环优化

// Bad
for ($i = 0; $i < count($arr); $i++)
// Good
$count = count($arr);
for ($i = 0; $i < $count; $i++)

3. 分支选择

4. 代码健壮性

函数与类 (Functions & Classes)

1. 路径与包含

2. 方法与内存

3. 文件读取

变量与内存 (Variables)

1. 局部变量 vs 全局变量

2. 递增运算

3. 及时回收

4. 引用参数

架构级优化 (Architecture)

1. 引擎升级

2. 缓存机制

3. 静态化与压缩

性能评估工具

实例

$it = 1000000; // 标准迭代次数
header('Content-Type: text/plain; charset=utf-8');

echo "PHP " . PHP_VERSION . " 综合性能基准测试 (迭代: $it)\n";
echo str_repeat('=', 75) . "\n";

/**
 * 1. 长度检查:isset() vs strlen()
 * 佐证:PHP 8+ 中 strlen 是 Specialized Opcode,性能已追平甚至超越 isset
 */
$str = 'hello_world_gemini';
$s   = microtime(true);
for ($i = 0; $i < $it; $i++) {
    $null = strlen($str) > 5;
}
$t_bad = microtime(true) - $s;

$s = microtime(true);
for ($i = 0; $i < $it; $i++) {
    $null = isset($str[5]);
}
$t_good = microtime(true) - $s;
printf("1. 长度检查 | Bad: strlen: %.4fs | Good: isset: %.4fs | 提升: %.1f%%\n", $t_bad, $t_good, (($t_bad - $t_good) / $t_bad) * 100);

/**
 * 2. 数组索引:引号 vs 常量查找 (PHP 8 模拟)
 * 佐证:不加引号会触发常量查找表,PHP 8+ 找不到常量会抛出 Fatal Error
 */
$row = ['id' => 123];
define('FAKE_ID', 'id');
$s = microtime(true);
for ($i = 0; $i < $it; $i++) {
    $val = $row[FAKE_ID];
}
$t_bad = microtime(true) - $s;

$s = microtime(true);
for ($i = 0; $i < $it; $i++) {
    $val = $row['id'];
}
$t_good = microtime(true) - $s;
printf("2. 数组引号 | Bad: 常量键: %.4fs | Good: 字符键: %.4fs | 提升: %.1f%%\n", $t_bad, $t_good, (($t_bad - $t_good) / $t_bad) * 100);

/**
 * 3. 存储位置:数组寻址 vs 局部变量
 * 佐证:局部变量存储在 CV 表,通过偏移量访问;数组需哈希计算 (Hash Lookup)
 */
$testArray = ['id' => 123];
$myId      = 123;
$s         = microtime(true);
for ($i = 0; $i < $it; $i++) {
    if ($testArray['id'] === 123) {
    }
}
$t_bad = microtime(true) - $s;

$s = microtime(true);
for ($i = 0; $i < $it; $i++) {
    if ($myId === 123) {
    }
}
$t_good = microtime(true) - $s;
printf("3. 存储寻址 | Bad: 数组寻址: %.4fs | Good: 局部变量: %.4fs | 提升: %.1f%%\n", $t_bad, $t_good, (($t_bad - $t_good) / $t_bad) * 100);

/**
 * 4. 空值判断:is_null() vs === null
 * 佐证:=== 是操作符,is_null 是内置函数。虽然 PHP 8 优化了后者,但操作符仍有微弱优势
 */
$var = null;
$s   = microtime(true);
for ($i = 0; $i < $it; $i++) {
    if (is_null($var)) {
    }
}
$t_bad = microtime(true) - $s;

$s = microtime(true);
for ($i = 0; $i < $it; $i++) {
    if ($var === null) {
    }
}
$t_good = microtime(true) - $s;
printf("4. 空值判断 | Bad: is_null:  %.4fs | Good: === null: %.4fs | 提升: %.1f%%\n", $t_bad, $t_good, (($t_bad - $t_good) / $t_bad) * 100);

/**
 * 5. 变量作用域:对象属性 vs 局部变量
 */
class Scope
{
    public $p = 0;
}

$obj   = new Scope();
$local = 0;
$s     = microtime(true);
for ($i = 0; $i < $it; $i++) {
    $obj->p++;
}
$t_bad = microtime(true) - $s;

$s = microtime(true);
for ($i = 0; $i < $it; $i++) {
    $local++;
}
$t_good = microtime(true) - $s;
printf("5. 变量存取 | Bad: 对象属性: %.4fs | Good: 局部变量: %.4fs | 提升: %.1f%%\n", $t_bad, $t_good, (($t_bad - $t_good) / $t_bad) * 100);

/**
 * 6. 集合处理 (公平竞赛与场景辨析)
 * 佐证:foreach赢在避开了闭包调用(Callback)开销;引用赢在避免内存申请
 */
$data = range(1, 1000);

// 6a. 原位修改:理论上的性能巅峰 (避开内存申请与函数调用)
$s = microtime(true);
for ($i = 0; $i < 1000; $i++) {
    foreach ($data as &$v) {
        $v *= 2;
    }
    unset($v);
}
$t_foreach_ref = microtime(true) - $s;
printf("6a. 原位修改 | foreach&: %.4fs (内存复用 + 无函数压栈)\n", $t_foreach_ref);

// 6b. 生成新数组:公平竞赛 (对比函数调用开销)
$s = microtime(true);
for ($i = 0; $i < 1000; $i++) {
    $res = array_map(fn($v) => $v * 2, $data);
}
$t_bad = microtime(true) - $s;

$s = microtime(true);
for ($i = 0; $i < 1000; $i++) {
    $res = [];
    foreach ($data as $v) {
        $res[] = $v * 2;
    }
}
$t_good = microtime(true) - $s;
printf("6b. 生成数组 | Bad: array_map:    %.4fs | Good: foreach: %.4fs | 提升: %.1f%%\n", $t_bad, $t_good, (($t_bad - $t_good) / $t_bad) * 100);

/**
 * 7. 魔术方法:__get vs 直接访问
 * 佐证:__get 涉及方法查找与动态调用,属于慢速路径 (Slow Path)
 */
class Magic
{
    private $d = ['b' => 1];
    public  $a = 1;

    public function __get($n)
    {
        return $this->d[$n] ?? null;
    }
}

$mg = new Magic();
$s  = microtime(true);
for ($i = 0; $i < $it; $i++) {
    $val = $mg->b;
}
$t_bad = microtime(true) - $s;

$s = microtime(true);
for ($i = 0; $i < $it; $i++) {
    $val = $mg->a;
}
$t_good = microtime(true) - $s;
printf("7. 魔术方法 | Bad: __get:    %.4fs | Good: 直接访问: %.4fs | 提升: %.1f%%\n", $t_bad, $t_good, (($t_bad - $t_good) / $t_bad) * 100);

/**
 * 8. 错误抑制符:@ 符号代价
 * 佐证:即使不报错,修改错误报告级别也会产生额外的系统调用开销
 */
$s = microtime(true);
for ($i = 0; $i < $it; $i++) {
    $x = @(1 / 1);
}
$t_bad = microtime(true) - $s;

$s = microtime(true);
for ($i = 0; $i < $it; $i++) {
    $x = 1 / 1;
}
$t_good = microtime(true) - $s;
printf("8. 抑制符号 | Bad: 使用@:   %.4fs | Good: 不使用@: %.4fs | 差距: %.1f倍\n", $t_bad, $t_good, $t_bad / $t_good);

/**
 * 9. 字符替换:盲目替换 vs 先查再换
 * 佐证:避免不必要的写操作 (Write Operation) 和内存申请
 */
$haystack = "Looking for a needle in this haystack";
$needle   = "nonexistent";
$s        = microtime(true);
for ($i = 0; $i < $it; $i++) {
    str_replace($needle, "xyz", $haystack);
}
$t_bad = microtime(true) - $s;

$s = microtime(true);
for ($i = 0; $i < $it; $i++) {
    if (strpos($haystack, $needle) !== false) {
        str_replace($needle, "xyz", $haystack);
    }
}
$t_good = microtime(true) - $s;
printf("9. 字符替换 | Bad: 直接替换: %.4fs | Good: 先查再换: %.4fs | 提升: %.1f%%\n", $t_bad, $t_good, (($t_bad - $t_good) / $t_bad) * 100);

echo str_repeat('=', 75) . "\n测试结束。\n";

输出

PHP 8.3.21 综合性能基准测试 (迭代: 1000000)
======================================================================
1. 长度检查 | Bad: strlen: 0.0195s | Good: isset: 0.0206s | 提升: -5.8%
2. 数组引号 | Bad: 常量键: 0.0240s | Good: 字符键: 0.0218s | 提升: 9.3%
3. 存储寻址 | Bad: 数组寻址: 0.0200s | Good: 局部变量: 0.0149s | 提升: 25.5%
4. 空值判断 | Bad: is_null:  0.0140s | Good: === null: 0.0140s | 提升: -0.3%
5. 变量存取 | Bad: 对象属性: 0.0168s | Good: 局部变量: 0.0135s | 提升: 19.6%
6. 集合处理 | array_map: 0.1015s | foreach&: 0.0114s | 提升: 88.8%
7. 魔术方法 | Bad: __get:    0.0783s | Good: 直接访问: 0.0178s | 提升: 77.2%
8. 抑制符号 | Bad: 使用@:   0.0237s | Good: 不使用@: 0.0166s | 差距: 1.4倍
9. 字符替换 | Bad: 直接替换: 0.0595s | Good: 先查再换: 0.0551s | 提升: 7.3%
======================================================================
测试结束。